/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#ifndef DEVMON_CSR_UTILS_H
#define DEVMON_CSR_UTILS_H

#include "app_schema.h"
#include <mc/dict.h>
#include <mc/engine.h>
#include <mc/json.h>
#include <mc/reflect.h>
#include <mutex>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>

namespace devmon {

using string_map_t = std::unordered_map<std::string, std::string>;

struct ref_sync_target {
    bool        is_global;
    std::string object_name;
    std::string interface_name;
    std::string prop_name;
};

struct instance_info_t {
    instance_info_t() = default;
    instance_info_t(const class_base_info& info) : app(info.app), path(info.path) {
    }
    instance_info_t(mc::engine::abstract_object* object)
        : app("devmon"), path(object->get_object_path()) {
    }

    bool                     framework    = false;
    bool                     ref_presence = false;
    std::string              app;
    std::string              path;
    std::string              parent;
    std::string              object_name;
    std::vector<std::string> references;
};

namespace csr_utils {
/**
 * 检查属性值是否为同步属性
 * @param prop_value 属性值
 * @return 是否为同步属性
 */
bool is_sync(std::string_view prop_value);

/**
 * 检查属性值是否为引用属性
 * @param prop_value 属性值
 * @return 是否为引用属性
 */
bool is_ref(std::string_view prop_value);

/**
 * 检查属性值是否为引用存在性属性
 * @param prop_value 属性值
 * @param class_name 类名
 * @param prop_name 属性名
 * @return 是否为引用存在性属性
 */
bool is_ref_presence(std::string_view prop_value, std::string_view class_name,
                     std::string_view prop_name);

/**
 * 检查属性值是否为函数调用
 * @param str 属性值
 * @return 是否为函数调用
 */
bool is_func_call(std::string_view str);

/**
 * 从对象名中提取类名
 * @param object_name 对象名
 * @return 类名
 */
std::string get_class_name(std::string object_name);

/**
 * 检查对象属性是否为整数类型
 * @param position 位置
 * @param object_name 对象名
 * @param prop_name 属性名
 * @return 是否为整数类型
 */
bool is_prop_type_integer(std::string position, std::string object_name, std::string prop_name);

/**
 * 从属性值中提取引用目标
 * @param prop_value 属性值
 * @return 引用目标列表
 */
std::vector<ref_sync_target> get_ref_targets(std::string prop_value);

/**
 * 从属性值中提取同步目标
 * @param prop_value 属性值
 * @return 同步目标列表
 */
std::vector<ref_sync_target> get_sync_targets(std::string prop_value);

/**
 * 替换同步对象名
 * @param prop_value 属性值
 * @param objects_map 对象映射表
 * @return 替换后的属性值
 */
std::string replace_sync_objects(std::string prop_value, string_map_t& objects_map);

/**
 * 替换引用对象名
 * @param prop_value 属性值
 * @param objects_map 对象映射表
 * @return 替换后的属性值
 */
std::string replace_ref_object(std::string prop_value, string_map_t& objects_map);

/**
 * 从属性值中提取表达式
 * @param prop_value 属性值
 * @param max_count 最大表达式数量，-1表示不限制
 * @return 表达式列表
 */
std::vector<std::string> get_prop_expr(std::string prop_value, int max_count = -1);

/**
 * 转换管理拓扑
 * @param management_topology 管理拓扑
 * @return 转换后的拓扑
 */
mc::dict convert_topology(const mc::dict& management_topology);

/**
 * 获取对象实例信息
 * @param position 位置
 * @param object_name 对象名
 * @param variable_map 变量替换映射表
 * @return 对象实例信息
 */
instance_info_t get_instance_info(std::string position, std::string object_name,
                                  mc::dict& variable_map);

/**
 * 获取对象属性所在接口和原属性名
 * @param position 位置
 * @param object_name 对象名
 * @param prop_name 属性名
 * @return 对象属性所在接口和原属性名
 */
std::tuple<std::string, std::string>
get_property_intf(std::string position, std::string object_name, std::string prop_name);

/**
 * 获取对象属性所在接口和原属性名
 * @param position 位置
 * @param target 引用或同步目标
 * @return 对象属性所在接口和原属性名
 */
std::tuple<std::string, std::string> get_property_intf(std::string      position,
                                                       ref_sync_target& target);

/**
 * 获取连接器位置
 * @param connector 连接器
 * @return 连接器位置
 */
std::string get_connector_position(mc::dict& connector);

/**
 * 获取同服务对象引用信息
 */
std::string get_local_ref_object_info(std::string_view object_name);

/**
 * 获取跨服务对象引用信息
 */
std::string get_remote_ref_object_info(std::string_view app, std::string_view path);

/**
 * 获取同服务属性引用信息
 */
std::string get_local_ref_property_info(std::string_view object_name, std::string_view property,
                                        std::string_view expr);

/**
 * 获取跨服务属性引用信息
 */
std::string get_remote_ref_property_info(std::string_view app, std::string_view path,
                                         std::string_view interface, std::string_view property,
                                         std::string_view expr);

/**
 * 获取属性同步信息
 */
std::string get_sync_property_info(
    std::string_view expr, std::string_view default_str,
    const std::vector<std::tuple<std::string, std::string, std::string, std::string>>& properties);
} // namespace csr_utils

struct parsed_sr_object {
    bool             ref_presence = false;
    std::string      app_name;
    std::string      class_name;
    std::string      object_name;
    std::string      path;
    mc::mutable_dict object_props;
    mc::mutable_dict extra_props;
};

struct parsed_sr_func_object {
    std::vector<std::string> app_names;
    std::string              class_name;
    std::string              object_name;
    mc::mutable_dict         object_props;
};

struct object_info_t {
    MC_REFLECTABLE("ObjectInfo")

    std::string ClassName;
    std::string ObjectName;
    std::string ObjectProps;
    std::string ObjectExtends;
};

struct object_group_t {
    MC_REFLECTABLE("ObjectGroup")

    std::string                Position;
    std::vector<object_info_t> Objects;
    uint32_t                   LifeCycleId;
};

using device_objects_map_t =
    std::unordered_map<std::string, std::unordered_map<std::string, mc::engine::abstract_object*>>;

/**
 * 对象组数据管理类
 */
class object_group_data {
public:
    static object_group_data& get_instance();
    static void reset_for_test();

    object_group_data() = default;
    object_group_t get_objects(std::string position, std::string owner);
    void           save_objects(std::string                                          position,
                                std::vector<std::shared_ptr<parsed_sr_object>>&      parsed_objects,
                                std::vector<std::shared_ptr<parsed_sr_func_object>>& parsed_func_objects);
    mc::dict       get_topology(std::string position);
    void           save_topology(std::string position, const mc::dict& topology);
    void           save_device_object(mc::engine::abstract_object* object, std::string position,
                                      std::string object_name);
    void           clear_device_objects(std::string position);
    bool           is_device_object(std::string position, std::string object_name);
    mc::engine::abstract_object* get_device_object(std::string position, std::string object_name);
    std::vector<std::string>     get_owners(std::string position);

private:
    // 二层哈希表 position -> owner -> object_group_t
    std::unordered_map<std::string, std::unordered_map<std::string, object_group_t>> m_objects;
    std::unordered_map<std::string, uint32_t>                 m_life_cycle_ids;
    std::unordered_map<std::string, std::vector<std::string>> m_owners_by_position;
    std::mutex                                                m_objects_mutex;
    std::unordered_map<std::string, mc::dict>                 m_topology_by_position;
    std::mutex                                                m_topology_mutex;
    device_objects_map_t                                      m_device_objects;
    std::mutex                                                m_device_objects_mutex;
};

} // namespace devmon

#endif // DEVMON_CSR_UTILS_H